package com.xy.xylive.api;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.xy.xylive.aop.Decrypt;
import com.xy.xylive.aop.Encrypt;
import com.xy.xylive.api.req.LiveLayoutChangeReq;
import com.xy.xylive.api.req.LiveSettingReq;
import com.xy.xylive.api.res.LiveLayoutRes;
import com.xy.xylive.api.res.StatRes;
import com.xy.xylive.common.ErrorCode;
import com.xy.xylive.common.PageUtils;
import com.xy.xylive.common.ServiceException;
import com.xy.xylive.config.XylinkConf;
import com.xy.xylive.domain.AudienceSetting;
import com.xy.xylive.domain.Live;
import com.xy.xylive.hstapi.HstApiResult;
import com.xy.xylive.hstapi.HstApiUtil;
import com.xy.xylive.hstapi.model.DataVideo;
import com.xy.xylive.hstapi.model.LayoutConfig;
import com.xy.xylive.hstapi.req.ChangeLayoutReq;
import com.xy.xylive.hstapi.req.LiveReq;
import com.xy.xylive.hstapi.req.PushReq;
import com.xy.xylive.hstapi.res.LayoutRes;
import com.xy.xylive.hstapi.res.PushRes;
import com.xy.xylive.mapper.AudienceSettingMapper;
import com.xy.xylive.service.ILiveService;
import com.xy.xylive.xyapi.LiveStatRes;
import com.xy.xylive.xyapi.LiveVideoReq;
import com.xy.xylive.xyapi.LiveVideoRes;
import com.xy.xylive.xyapi.LiveVideoV3Api;
import com.xy.xylive.xyapi.LiveVideoV5Api;
import com.xy.xylive.xyapi.ThirdpartLiveVideo;
import com.xylink.config.SDKConfigMgr;
import com.xylink.model.SdkCloudMeetingRoomRequest;
import com.xylink.model.SdkMeeting;
import com.xylink.sdk.conferenceControl.CreateMeetingApi;
import com.xylink.sdk.liveVideo.v3.LiveVideoApi;
import com.xylink.util.Result;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import cn.hutool.poi.excel.ExcelUtil;
import cn.hutool.poi.excel.ExcelWriter;
import lombok.extern.slf4j.Slf4j;

/**
 * 直播Controller
 *
 * @author ghostsf
 * @date 2024-05-19
 */
@RestController
@RequestMapping("/live")
@Slf4j
public class LiveController
{
    @Autowired
    private ILiveService liveService;

    @Autowired
    private XylinkConf xylinkConf;

    @Autowired
    private HstApiUtil hstApiUtil;

    @Autowired
    private AudienceSettingMapper audienceSettingMapper;

    /**
     * 查询直播列表
     */
    @GetMapping("/list")
    public PageR<Live> list(com.xy.xylive.api.req.LiveReq liveReq)
    {
        if(liveReq.getIsSuper() == null) {
            throw new ServiceException(ErrorCode.PARAMS_ERROR);
        }
        PageUtils.startPage();
        Integer isSuper = liveReq.getIsSuper();
        if(isSuper == 0) {
            if(StrUtil.isNotBlank(liveReq.getHstMeetingId())) {
                boolean hasData = liveService.checkByUserIdAndHstMeetingId(liveReq.getUserId(), liveReq.getHstMeetingId());
                if(!hasData) {
                    return PageR.ok(new ArrayList<>());
                }
            }
        }
        Live live = new Live();
        BeanUtil.copyProperties(liveReq, live);
        List<Live> list = liveService.selectLiveList(live);
        return PageR.ok(list);
    }

    /**
     * 获取直播详细信息
     */
    @GetMapping("/{id}")
    @Encrypt
    public R<Live> getInfo(@PathVariable Integer id)
    {
        return R.ok(liveService.selectLiveById(id));
    }

    /**
     * 新增直播
     */
    @PostMapping
    @Transactional
    public R add(@RequestBody Live live) throws IOException {
        if(StrUtil.hasBlank(live.getHstMeetingId(), live.getUserId(), live.getTitle())) {
            throw new ServiceException(ErrorCode.PARAMS_ERROR);
        }
        if(live.getStartTime() == null || live.getEndTime() == null) {
            throw new ServiceException(ErrorCode.PARAMS_ERROR);
        }

        // 默认自动先删除好视通直播
        // 查询本地是否有当前好视通会议直播记录
        // 可能会将其他用户创建的好视通直播数据删除 前端提醒确认下
        Live liveQueryForHstLive = new Live();
        liveQueryForHstLive.setHstMeetingId(live.getHstMeetingId());
        liveQueryForHstLive.setIsDelete(0);
        List<Live> liveList = liveService.selectLiveList(liveQueryForHstLive);
        if(liveList.size() > 1) {
            log.error("数据业务逻辑错误：当前会议存在多个直播记录 好视通会议号：{}， 存在: {}", live.getHstMeetingId(), liveList.size());
        }
        for(Live liveItem: liveList) {
            LiveVideoApi liveVideoApi = new LiveVideoApi();
            Result deleteLiveByIdsResult = liveVideoApi.deleteLive(xylinkConf.getEnterpriseId(), SDKConfigMgr.getAccessToken(), liveItem.getXyMeetingNumber(), null, liveItem.getXyLiveId());
            if(!deleteLiveByIdsResult.isSuccess()) {
                if(deleteLiveByIdsResult.getErrorStatus() != 60025) {
                    log.error("小鱼自动删除直播失败：" + deleteLiveByIdsResult.getErrorStatus() + " " + deleteLiveByIdsResult.getErrorMsg());
//                    throw new ServiceException("小鱼自动删除直播失败：" + deleteLiveByIdsResult.getErrorStatus() + " " + deleteLiveByIdsResult.getErrorMsg());
                }
            }
            HstApiResult<Integer> hstApiResult = hstApiUtil.deleteLive(String.valueOf(liveItem.getHstLiveId()));
            if(!hstApiResult.isSuccess()) {
                if(hstApiResult.getResCode() != 30103) {
//                    log.error("好视通自动删除直播失败：" + hstApiResult.getResCode() + " " + hstApiResult.getResMessage());
                    throw new ServiceException("好视通自动删除直播失败：" + hstApiResult.getResCode() + " " + hstApiResult.getResMessage());
                }
            }
            liveService.deleteLiveById(liveItem.getId());
        }

        // 小鱼 会议  直播 -> 好视通直播 -> 好视通推流
        SdkCloudMeetingRoomRequest sdkCloudMeetingRoomRequest = new SdkCloudMeetingRoomRequest();
        sdkCloudMeetingRoomRequest.setMeetingName(live.getTitle());
        CreateMeetingApi createMeetingApi = new CreateMeetingApi();
        SdkMeeting sdkMeeting = createMeetingApi.createMeetingV2(xylinkConf.getEnterpriseId(), SDKConfigMgr.getAccessToken(), sdkCloudMeetingRoomRequest);

        LiveVideoReq liveVideo = new LiveVideoReq();
        liveVideo.setTitle(live.getTitle());
//        liveVideo.setStartTime(DateUtil.offsetSecond(DateUtil.date(), 1).getTime());
//        // 直播默认3天结束
//        liveVideo.setEndTime(DateUtil.offsetDay(DateUtil.date(), 3).getTime());
        liveVideo.setStartTime(live.getStartTime().getTime());
        liveVideo.setEndTime(live.getEndTime().getTime());
        liveVideo.setDetail(live.getDetail());
        liveVideo.setAutoRecording(true);
        liveVideo.setAutoPublishRecording(true);
        LiveVideoV5Api liveVideoV5Api = new LiveVideoV5Api();
        Result<LiveVideoRes> liveVideoForConferenceResult = liveVideoV5Api.scheduleLive(xylinkConf.getEnterpriseId(), SDKConfigMgr.getAccessToken(), sdkMeeting.getMeetingNumber(), liveVideo);
        if(!liveVideoForConferenceResult.isSuccess()) {
            throw new ServiceException("创建小鱼直播失败 " + liveVideoForConferenceResult.getErrorMsg());
        }
        LiveVideoRes liveVideoRes = liveVideoForConferenceResult.getData();

        LiveReq liveReq = new LiveReq();
        liveReq.setLiveName(live.getTitle());
        liveReq.setConfRoomId(Integer.parseInt(live.getHstMeetingId()));
        liveReq.setStatus(1);
        liveReq.setStartTime(DateUtil.format(live.getStartTime(), DatePattern.NORM_DATETIME_PATTERN));
        liveReq.setEndTime(DateUtil.format(live.getEndTime(), DatePattern.NORM_DATETIME_PATTERN));
        liveReq.setLiveInfo(live.getDetail());
        liveReq.setAnchorName(live.getTitle());
        HstApiResult<Integer> hstApiResult = hstApiUtil.createLive(liveReq);
        log.info("好视通直播创建结果：" + JSONUtil.toJsonStr(hstApiResult));
        if(!hstApiResult.isSuccess()) {
            // 已创建直播
            if(hstApiResult.getResCode() == 30118) {
                throw new ServiceException("当前会议已创建直播，请先删除之前的直播");
            }
            throw new ServiceException("创建好视通直播失败 " + hstApiResult.getResCode() + " " +hstApiResult.getResMessage());
        }

        PushReq pushReq = new PushReq();
        pushReq.setName("小鱼");
        pushReq.setType("OTHER");
        pushReq.setRtmpAddr("rtmp://video-center.alivecdn.com/");
        pushReq.setLiveCode(liveVideoRes.getPushUrl().substring("rtmp://video-center.alivecdn.com/".length()));
        pushReq.setAttr("null");
        HstApiResult<PushRes> pushResHstApiResult = hstApiUtil.createPush(String.valueOf(hstApiResult.getData()), pushReq);
        if(!pushResHstApiResult.isSuccess()) {
            throw new ServiceException("创建好视通直播推流失败 " + pushResHstApiResult.getResMessage());
        }

        live.setStatus(0);
        live.setXyLiveId(liveVideoRes.getLiveId());
        live.setXyMeetingNumber(sdkMeeting.getMeetingNumber());
        live.setHstLiveId(hstApiResult.getData());
        live.setHstLivePlatformId(pushResHstApiResult.getData().getId());
        live.setPushUrl(liveVideoRes.getPushUrl());
        live.setPullUrl(liveVideoRes.getPullUrls().get(0).getVideoM3u8());
        live.setCreateTime(new Date());

        int r = liveService.insertLive(live);
        if (r <= 0) {
            throw new ServiceException("创建直播失败");
        }

        // 同步插入默认的直播观众设置数据
        AudienceSetting audienceSetting = new AudienceSetting();
        audienceSetting.setLiveId(live.getId());
        audienceSetting.setCreateTime(new Date());
//        audienceSetting.setNeedFields("name,phone");
//        audienceSetting.setWaterFields("name,phone");
        audienceSettingMapper.insertAudienceSetting(audienceSetting);

        return R.ok(r);
    }

    /**
     * 修改直播
     */
    @PutMapping
    @Transactional
    public R edit(@RequestBody Live live) throws IOException {
        LiveVideoReq liveVideoReq = new LiveVideoReq();
        BeanUtil.copyProperties(live, liveVideoReq);
        LiveVideoV5Api liveVideoV5Api = new LiveVideoV5Api();
        Result<LiveVideoRes> liveVideoForConferenceResult = liveVideoV5Api.updateLive(xylinkConf.getEnterpriseId(), SDKConfigMgr.getAccessToken(), live.getXyMeetingNumber(), live.getXyLiveId(), liveVideoReq);
        if(!liveVideoForConferenceResult.isSuccess()) {
            throw new ServiceException("修改小鱼直播失败 " + liveVideoForConferenceResult.getErrorMsg());
        }
        live.setUpdateTime(new Date());
        return R.ok(liveService.updateLive(live));
    }

    /**
     * 设置直播
     */
    @PostMapping("/setting")
    @Transactional
    public R setting(@RequestBody LiveSettingReq liveSettingReq) throws IOException {
        if(liveSettingReq.getId() == null) {
            throw new ServiceException(ErrorCode.PARAMS_ERROR);
        }
        Live live = liveService.selectLiveById(liveSettingReq.getId());
        if(live == null) {
            throw new ServiceException(ErrorCode.PARAMS_ERROR);
        }
        BeanUtil.copyProperties(liveSettingReq, live);
        return R.ok(liveService.updateLive(live));
    }

    /**
     * 控制直播
     * @param id
     * @param status 动作：start(开始) / end(结束)
     * @return
     */
    @PostMapping("/control/{id}/{status}")
    @Transactional
    public R control(@PathVariable Integer id, @PathVariable String status) {
        if(StrUtil.isBlank(status)) {
            throw new ServiceException(ErrorCode.PARAMS_ERROR);
        }
        Live live = liveService.selectLiveById(id);
        if(live == null) {
            throw new ServiceException(ErrorCode.PARAMS_ERROR);
        }
        // TODO: 小鱼直播控制接口有问题
//        LiveVideoApi liveVideoApi = new LiveVideoApi();
//        Status statusReq = new Status();
//        statusReq.setStatus(status);
//        Result xyResult = liveVideoApi.controlLive(xylinkConf.getEnterpriseId(), SDKConfigMgr.getAccessToken(), live.getXyMeetingNumber(), null, live.getXyLiveId(), statusReq);
//        if(!xyResult.isSuccess()) {
//            throw new ServiceException("小鱼控制直播"+status+"失败：" + xyResult.getErrorStatus() + ":" + xyResult.getErrorMsg());
//        }

        if(status.equals("pause")) {
            // 暂停只停止推流 不关直播
            HstApiResult hstApiResult2 = hstApiUtil.controlPush(String.valueOf(live.getHstLiveId()), String.valueOf(live.getHstLivePlatformId()), "stop");
            log.info(JSONUtil.toJsonStr(hstApiResult2));
            if(!hstApiResult2.isSuccess()) {
                // 忽略报错
                if(!("start".equals(status) && hstApiResult2.getResCode() == 30202) && !("stop".equals(status) && hstApiResult2.getResCode() == 30203)) {
                    throw new ServiceException("好视通控制直播推流"+status+"失败：" + hstApiResult2.getResMessage());
                }
            }
        } else if(status.equals("recovery")) {
            // 暂停恢复推流 不关直播
            HstApiResult hstApiResult2 = hstApiUtil.controlPush(String.valueOf(live.getHstLiveId()), String.valueOf(live.getHstLivePlatformId()), "start");
            log.info(JSONUtil.toJsonStr(hstApiResult2));
            if(!hstApiResult2.isSuccess()) {
                // 忽略报错
                if(!("start".equals(status) && hstApiResult2.getResCode() == 30202) && !("stop".equals(status) && hstApiResult2.getResCode() == 30203)) {
                    throw new ServiceException("好视通控制直播推流"+status+"失败：" + hstApiResult2.getResMessage());
                }
            }
        } else{
            HstApiResult hstApiResult = hstApiUtil.controlLive(status, String.valueOf(live.getHstLiveId()));
            log.info(JSONUtil.toJsonStr(hstApiResult));
            if(!hstApiResult.isSuccess()) {
                // 忽略报错
                if(!("start".equals(status) && hstApiResult.getResCode() == 30104) && !("stop".equals(status) && hstApiResult.getResCode() == 30105)) {
                    throw new ServiceException("好视通直播"+status+"失败：" + hstApiResult.getResCode() + " " +hstApiResult.getResMessage());
                }
            }
            HstApiResult hstApiResult2 = hstApiUtil.controlPush(String.valueOf(live.getHstLiveId()), String.valueOf(live.getHstLivePlatformId()), status);
            log.info(JSONUtil.toJsonStr(hstApiResult2));
            if(!hstApiResult2.isSuccess()) {
                // 忽略报错
                if(!("start".equals(status) && hstApiResult2.getResCode() == 30202) && !("stop".equals(status) && hstApiResult2.getResCode() == 30203)) {
                    throw new ServiceException("好视通控制直播推流"+status+"失败：" + hstApiResult2.getResMessage());
                }
            }
        }

        if("start".equals(status)) {
            live.setStatus(1);
        } else if("pause".equals(status)) {
            live.setStatus(2);
        } else if("recovery".equals(status)) {
            live.setStatus(1);
        } else if("stop".equals(status))  {
            live.setStatus(3);
        }

        live.setUpdateTime(new Date());
        return R.ok(liveService.updateLive(live));
    }

    /**
     * 删除直播
     */
    @DeleteMapping("/{id}")
    @Transactional
    public R remove(@PathVariable Integer id) throws IOException {
        Live live = liveService.selectLiveById(id);
        if(live == null) {
            throw new ServiceException(ErrorCode.PARAMS_ERROR);
        }
        // 基本状态数据判断
        if (live.getIsDelete() == 1) {
            throw new ServiceException("该直播已删除");
        }
        if (live.getStatus() == 1 || live.getStatus() == 2) {
            throw new ServiceException("该直播当前状态不能删除");
        }
        LiveVideoApi liveVideoApi = new LiveVideoApi();
        Result deleteLiveByIdsResult = liveVideoApi.deleteLive(xylinkConf.getEnterpriseId(), SDKConfigMgr.getAccessToken(), live.getXyMeetingNumber(), null, live.getXyLiveId());
        if(!deleteLiveByIdsResult.isSuccess()) {
            // 60025 live.notexists
            if(deleteLiveByIdsResult.getErrorStatus() != 60025) {
//                log.error("小鱼删除直播失败：" + deleteLiveByIdsResult.getErrorStatus() + " " + deleteLiveByIdsResult.getErrorMsg());
                throw new ServiceException("小鱼删除直播失败：" + deleteLiveByIdsResult.getErrorStatus() + " " + deleteLiveByIdsResult.getErrorMsg());
            }
        }
        HstApiResult<Integer> hstApiResult = hstApiUtil.deleteLive(String.valueOf(live.getHstLiveId()));
        if(!hstApiResult.isSuccess()) {
            if(hstApiResult.getResCode() != 30103) {
//                    log.error("好视通删除直播失败：" + hstApiResult.getResCode() + " " + hstApiResult.getResMessage());
                throw new ServiceException("好视通删除直播失败：" + hstApiResult.getResCode() + " " + hstApiResult.getResMessage());
            }
        }
        return R.ok(liveService.deleteLiveById(id));
    }

    /**
     * 获取直播统计信息
     */
    @GetMapping(value = "/stat/{id}")
    public R<StatRes> getStatInfo(@PathVariable("id") Integer id) throws IOException {
        Live live = liveService.selectLiveById(id);
        if(live == null) {
            throw new ServiceException(ErrorCode.PARAMS_ERROR);
        }

        StatRes statRes = new StatRes();
        statRes.setViewCount(live.getViewCount());
        LiveVideoV3Api liveVideoV3Api = new LiveVideoV3Api();
        Result<LiveStatRes> liveStatResResult = liveVideoV3Api.actualDuration(xylinkConf.getEnterpriseId(), SDKConfigMgr.getAccessToken(), live.getXyLiveId());
        if(!liveStatResResult.isSuccess()) {
            throw new ServiceException("小鱼直播时长查询失败：" + liveStatResResult.getErrorStatus() + " " + liveStatResResult.getErrorMsg());
        }
        statRes.setDuration(liveStatResResult.getData().getActualDuration());

        // live
        live.setDuration(liveStatResResult.getData().getActualDuration());
        liveService.updateLive(live);

        return R.ok(statRes);
    }

    /**
     * 更新直播观看次数
     */
    @PostMapping("/updateViewCount")
    @Encrypt
    public R updateViewCount(@RequestBody @Decrypt Live live) {
        Live liveFromDb = liveService.selectLiveById(live.getId());
        if(liveFromDb == null) {
            throw new ServiceException(ErrorCode.PARAMS_ERROR);
        }
        int viewCount = liveFromDb.getViewCount() == null ? 0: liveFromDb.getViewCount();
        liveFromDb.setViewCount(viewCount + 1);
        return R.ok(liveService.updateLive(liveFromDb));
    }

    /**
     * 查看直播回放
     */
    @GetMapping("/getLiveReplay/{id}")
    public R<ThirdpartLiveVideo[]> getLiveReplay(@PathVariable Integer id) throws IOException {
        Live liveFromDb = liveService.selectLiveById(id);
        if(liveFromDb == null) {
            throw new ServiceException(ErrorCode.PARAMS_ERROR);
        }
        LiveVideoV5Api liveVideoV5Api = new LiveVideoV5Api();
        Result<ThirdpartLiveVideo[]> thirdpartLiveVideoResult = liveVideoV5Api.liveVideoList(xylinkConf.getEnterpriseId(), SDKConfigMgr.getAccessToken(), liveFromDb.getXyLiveId(), liveFromDb.getXyMeetingNumber());
        if(!thirdpartLiveVideoResult.isSuccess()) {
            throw new ServiceException("小鱼直播回放查询失败：" + thirdpartLiveVideoResult.getErrorStatus() + " " + thirdpartLiveVideoResult.getErrorMsg());
        }
        ThirdpartLiveVideo[] thirdpartLiveVideoArr = thirdpartLiveVideoResult.getData();
        if(CollectionUtil.isNotEmpty(Arrays.asList(thirdpartLiveVideoArr))) {
            throw new ServiceException("暂无直播回放数据");
        }
//        Video video = new Video();
//        video.setStartTimestamp(new Date().getTime());
//        video.setEndTimestamp(DateUtil.offsetMinute(new Date(), 10).getTime());
//        video.setUrl("https://v17.dogevideo.com/vcloud/17/v/20190424/1556036075_818c4125ec9c8cbc7a7a8a7cc1601512/1037/7d515b22c4958598c0fbd1e6290a5ca5.mp4?vkey=F3EA69&tkey=1716601504321be2fc51&auth_key=1716615904-hYsAoKTytRZm5pWM-976730564-6045670b07b8a94a4e0444791b9af5b1");
//        conferenceLiveVideosArr[0].getVideos().add(video);
//        conferenceLiveVideosArr[0].getVideos().add(video);
        return R.ok(thirdpartLiveVideoArr);
    }

    /**
     * 获取直播布局
     */
    @GetMapping("/getLayout/{id}")
    public R<LiveLayoutRes> getLayout(@PathVariable Integer id) {
        if(id == null) {
            throw new ServiceException(ErrorCode.PARAMS_ERROR);
        }
        Live liveFromDb = liveService.selectLiveById(id);
        if(liveFromDb == null) {
            throw new ServiceException(ErrorCode.PARAMS_ERROR);
        }
        if(liveFromDb.getHstLiveId() == null) {
            log.error("getLayout hstLiveId is null");
            throw new ServiceException(ErrorCode.PARAMS_ERROR);
        }
        HstApiResult<LayoutRes> hstApiResult = hstApiUtil.getLayout(String.valueOf(liveFromDb.getHstLiveId()));
        log.info(JSONUtil.toJsonStr(hstApiResult));
        if(!hstApiResult.isSuccess()) {
            throw new ServiceException("好视通切换直播布局失败：" + hstApiResult.getResMessage());
        }
        LiveLayoutRes liveLayoutRes = new LiveLayoutRes();
        LayoutRes layoutRes = hstApiResult.getData();
        com.xy.xylive.hstapi.model.Video video = layoutRes.getVideo();
        if(video == null) {
            log.error("好视通直播布局异常 缺少video数据");
            throw new ServiceException(ErrorCode.ERROR);
        }
        if("video_avg_6".equals(video.getSolutionCode())){
            liveLayoutRes.setLayoutMode(1);
        } else if(video.getSolutionCode().contains("separation")) {
            liveLayoutRes.setLayoutMode(2);
        } else if(video.getSolutionCode().contains("pip")) {
            liveLayoutRes.setLayoutMode(3);
        }

        liveLayoutRes.setMaxVideoCount(layoutRes.getMaxVideoCount());
        liveLayoutRes.setId(id);
        liveLayoutRes.setSyncSwitch(0);
        return R.ok(liveLayoutRes);
    }

    /**
     * 切换直播布局
     */
    @PostMapping("/changeLayout")
    public R changeLayout(@RequestBody LiveLayoutChangeReq liveLayoutChange) {
        if(liveLayoutChange.getId() == null || liveLayoutChange.getLayoutMode() == null) {
            throw new ServiceException(ErrorCode.PARAMS_ERROR);
        }
        Live liveFromDb = liveService.selectLiveById(liveLayoutChange.getId());
        if(liveFromDb == null) {
            throw new ServiceException(ErrorCode.PARAMS_ERROR);
        }

        ChangeLayoutReq changeLayoutReq = new ChangeLayoutReq();
        if(liveLayoutChange.getSyncSwitch() != null) {
            changeLayoutReq.setSyncSwitch(liveLayoutChange.getSyncSwitch());
        }
        if(liveLayoutChange.getMaxVideoCount() != null) {
            changeLayoutReq.setMaxVideoCount(liveLayoutChange.getMaxVideoCount());
        }
        LayoutConfig layoutConfig = new LayoutConfig();
        if(liveLayoutChange.getLayoutMode() == 1) {
            // 画廊模式
            layoutConfig.setMode("auto");
            com.xy.xylive.hstapi.model.Video video = new com.xy.xylive.hstapi.model.Video();
            video.setSolutionCode("video_avg_6");
            layoutConfig.setVideo(video);
            DataVideo dataVideo = new DataVideo();
            dataVideo.setSolutionCode("separation_data_1+5");
            layoutConfig.setDataVideo(dataVideo);
            changeLayoutReq.setLayoutConfig(layoutConfig);
        } else if(liveLayoutChange.getLayoutMode() == 2) {
            // 演讲模式
            layoutConfig.setMode("auto");
            com.xy.xylive.hstapi.model.Video video = new com.xy.xylive.hstapi.model.Video();
            video.setSolutionCode("separation_video_1+5");
            layoutConfig.setVideo(video);
            DataVideo dataVideo = new DataVideo();
            dataVideo.setSolutionCode("separation_data_1+5");
            layoutConfig.setDataVideo(dataVideo);
            changeLayoutReq.setLayoutConfig(layoutConfig);
        } else if(liveLayoutChange.getLayoutMode() == 3) {
            // 画中画模式
            layoutConfig.setMode("auto");
            com.xy.xylive.hstapi.model.Video video = new com.xy.xylive.hstapi.model.Video();
            video.setSolutionCode("pip_video_right_1+5");
            layoutConfig.setVideo(video);
            DataVideo dataVideo = new DataVideo();
            dataVideo.setSolutionCode("pip_data_right_1+5");
            layoutConfig.setDataVideo(dataVideo);
            changeLayoutReq.setLayoutConfig(layoutConfig);
        } else {
            throw new ServiceException(ErrorCode.PARAMS_ERROR);
        }
        HstApiResult hstApiResult = hstApiUtil.changeLayout(String.valueOf(liveFromDb.getHstLiveId()), changeLayoutReq);
        log.info(JSONUtil.toJsonStr(hstApiResult));
        if(!hstApiResult.isSuccess()) {
            throw new ServiceException("好视通切换直播布局失败：" + hstApiResult.getResMessage());
        }
        return R.ok();
    }

    /**
     * 导出
     * @param live
     */
    @PostMapping("/export")
    public void export(HttpServletResponse response, @RequestBody Live live) throws IOException {
        List<Live> list = liveService.selectLiveList(live);
        ExcelWriter writer = ExcelUtil.getWriter(true);

        //自定义标题别名
        writer.addHeaderAlias("id", "ID");
        writer.setColumnWidth(0, 30);

        writer.addHeaderAlias("hstMeetingId", "会议ID");
        writer.setColumnWidth(1, 30);

        writer.addHeaderAlias("userId", "直播发起人");
        writer.setColumnWidth(2, 30);

        writer.addHeaderAlias("title", "直播主题");
        writer.setColumnWidth(3, 30);

        writer.addHeaderAlias("detail", "直播详情");
        writer.setColumnWidth(4, 30);

        writer.addHeaderAlias("startTime", "直播开始时间");
        writer.setColumnWidth(5, 30);

        writer.addHeaderAlias("endTime", "直播结束时间");
        writer.setColumnWidth(6, 30);

        writer.addHeaderAlias("viewCount", "观看人数");
        writer.setColumnWidth(7, 30);

        writer.addHeaderAlias("durationText", "实际直播时长");
        writer.setColumnWidth(8, 30);

        writer.addHeaderAlias("statusName", "状态");
        writer.setColumnWidth(9, 30);

        writer.addHeaderAlias("createTime", "创建时间");
        writer.setColumnWidth(10, 30);

        writer.addHeaderAlias("updateTime", "修改时间");
        writer.setColumnWidth(11, 30);

        writer.setOnlyAlias(true);
        writer.autoSizeColumnAll();

        // 一次性写出内容，使用默认样式，强制输出标题
        writer.write(list, true);

        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8");
        response.setHeader("Content-Disposition","attachment;filename=test.xlsx");
        ServletOutputStream out=response.getOutputStream();

        writer.flush(out, true);
        // 关闭writer，释放内存
        writer.close();
        //此处记得关闭输出Servlet流
        IoUtil.close(out);
    }


}
